home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1996 January / macformat-033.iso / mac / Shareware City / Developers / ABox.v1.8 / CPlus Files / ABox.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-23  |  57.0 KB  |  2,073 lines  |  [TEXT/MMCC]

  1. /*    
  2.     Copyright Â© 1991-1995 by TopSoft Inc.  All rights reserved.
  3.  
  4.     You may distribute this file under the terms of the TopSoft
  5.     Artistic License, accompanying this package.
  6.     
  7.     This file was developed by George (ty) Tempel in connection with TopSoft, Inc..
  8.     See the Modification History for more details.
  9.  
  10. Product
  11.     About Box
  12.  
  13. FILE
  14.     ABox.c
  15.  
  16. NAME
  17.     ABox.c, part of the ABox project source code,
  18.     responsible for the top level handling of the AboutBox.
  19.  
  20. DESCRIPTION
  21.     This file contains defines for the about box modules.
  22.     
  23. DEVELOPED BY
  24.     George (ty) Tempel                netromancr@aol.com
  25.     All code in this file, and its associated header file was
  26.     Created by George (ty) Tempel in connection with the TopSoft, Inc.
  27.     "FilterTop" application development, except where noted.
  28.  
  29. CARETAKER - George (ty) Tempel <netromancr@aol.com>
  30.      Please consult this person for any changes or suggestions to this file.
  31.  
  32. MODIFICATION HISTORY
  33.  
  34.     dd mmm yy    -    xxx    -    patchxx: description of patch
  35.     10 June 94    -    ty    -    Initial Version Created
  36.     20-july-94    -    ty    -    initial version released
  37.     22-july-94    -    ty    -    1.0.3 -    added correct modeless dialog resource,
  38.                                     corrected code for clicking to foreground
  39.     25-july-94    -    ty    -    1.0.4 -    corrected code (again) for clicking to 
  40.                                     foreground via title-bar click
  41.     28-july-94    -    ty    -    1.0.6 - added and rearranged code to correctly
  42.                                     deactivate the topic list when moved to
  43.                                     the background (within the layer or
  44.                                     across the layers)
  45.     23-may-95    -    ty    -    changes for compatibility with the CodeWarrior CW6
  46.                             release and the associated Universal Headers from Apple:
  47.                             most methods that returned references now have "Ref" at
  48.                             the end of their methods names to prevent possible collisions
  49.                             with datatypes and classes of the same name (older versions
  50.                             of the compiler didn't have a problem with this).
  51.  
  52. */
  53.  
  54. /*===========================================================================*/
  55.  
  56. /*======= Segmentation directives ========*/
  57.  
  58. #ifdef USE_MANUAL_SEGMENTATION
  59. #pragma segment ty
  60. #endif
  61.  
  62. /*============ Header files ==============*/
  63.  
  64.  
  65. #include     "ABox.h"
  66. #include    "ABoxDefs.h"
  67. #include    "ABUEnvDialog.h"
  68. #include    "ABSound.h"
  69.  
  70. /*=============== Globals ================*/
  71.  
  72. /*================ CODE ==================*/
  73.  
  74. /*=============================== ABox::ABox ================================*/
  75.  
  76. ABox::ABox(void)
  77. {
  78.     //    initialize the properties...
  79.     this->HomeFolderRef() = NULL;
  80.     this->FirstTopicRef() = 1;
  81.     this->FirstSlideRef() = 1;
  82.     this->SplashTimeRef() = kABoxNoSplash;
  83.     this->CallerResFileRef() = ::CurResFile();
  84.     this->UpdaterRef() = NULL;
  85.     this->ModalIndicatorRef() = kABoxModal;
  86.     this->AppNameAndVersionRef() = NULL;
  87.     this->WindowNameRef() = NULL;
  88.     this->DialogIDRef() = kABmodalDialog;
  89.     this->TextFontRef() = kABoxTextFont;
  90.     this->TextSizeRef() = kABoxTextSize;
  91.     this->TextFaceRef() = kABoxTextFace;
  92.     this->ListHandleRef() = NULL;
  93.  
  94.     this->InBackgroundFlagRef() = false;
  95.     this->ReportMemoryFlagRef() = false;
  96.     
  97.     this->UseSoundMgrFlagRef() = this->UseDragMgrFlagRef() = this->UseSpeechMgrFlagRef() = true;
  98.     
  99.     //    now for the private elements
  100.     this->TopicsRef() = new ABTopicList;
  101.     this->WindowRef() = NULL;
  102.     this->ThreadsHandlerRef() = NULL;
  103.     this->WindowUpFlagRef() = false;
  104.     this->ModalUPPRef() = NewModalFilterProc (this->ModalEventFilter);
  105. }    // end ABox
  106.  
  107.  
  108.  
  109.  
  110.  
  111. /*=============================== ABox::~ABox ================================*/
  112.  
  113. ABox::~ABox(void)
  114. {
  115.     (void)Close();
  116.  
  117.     if (this->TopicsRef())
  118.     {
  119.         delete this->TopicsRef();
  120.         this->TopicsRef() = NULL;
  121.     } 
  122.     
  123.     if (this->UpdaterRef())
  124.     {
  125.         DisposeRoutineDescriptor(this->UpdaterRef());
  126.         this->UpdaterRef() = NULL;
  127.     } // end if block
  128.     
  129.     if (this->ThreadsHandlerRef())
  130.     {
  131.         DisposeRoutineDescriptor(this->ThreadsHandlerRef());
  132.         this->ThreadsHandlerRef() = NULL;
  133.     } // end if block
  134.     
  135.     if (this->HomeFolderRef())
  136.     {
  137.         ::DisposPtr((Ptr)this->HomeFolderRef());
  138.         this->HomeFolderRef() = NULL;
  139.     }
  140.     
  141.     if (this->AppNameAndVersionRef())
  142.     {
  143.         ::DisposPtr((Ptr)this->AppNameAndVersionRef());
  144.         this->AppNameAndVersionRef() = NULL;
  145.     }
  146.     
  147.     if (this->WindowNameRef())
  148.     {
  149.         ::DisposPtr((Ptr)this->WindowNameRef());
  150.         this->WindowNameRef() = NULL;
  151.     }
  152.     
  153.     if (this->ModalUPPRef()) 
  154.     {
  155.         DisposeRoutineDescriptor (this->ModalUPPRef());
  156.     }    //    end if block
  157.  
  158. }    // end ~ABox
  159.  
  160.  
  161.  
  162.  
  163. /*=============================== ABox::Close ================================*/
  164. OSErr    ABox::Close(void)
  165. {
  166.     OSErr    error = noErr;
  167.     
  168.             
  169.     //    hold everything!
  170.     error = Stop();
  171.     
  172.     if (this->ListHandleRef())
  173.     {
  174.         ::LDispose(this->ListHandleRef());
  175.         this->ListHandleRef() = NULL;
  176.     } 
  177.     
  178.     if (this->WindowRef())
  179.     {
  180.         ::HideWindow(this->WindowRef());
  181.         ::DisposeDialog(this->WindowRef());
  182.         this->WindowRef() = NULL;
  183.         this->WindowUpFlagRef() = false;
  184.     }
  185.     
  186.     return error;
  187. }    // end Close
  188.  
  189.  
  190.  
  191.  
  192. /*=============================== ABox::GetProperty ================================*/
  193. OSErr    ABox::GetProperty (ABProperty prop, void *ptr, long *ptrSize)
  194. {
  195.     OSErr    error = noErr;
  196.     long    pSize;
  197.     
  198.     //    begin here...
  199.     //
  200.     if (!ptr)
  201.         return kABPropertyNullStorage;
  202.     
  203.     switch (prop)
  204.     {
  205.         case    kABoxUseSpeechMgr:
  206.                     *((Boolean *)ptr) = this->UseSpeechMgrFlagRef();
  207.                     pSize = kABoxUseSpeechMgrSize;
  208.                     break;
  209.         case    kABoxUseDragMgr:
  210.                     *((Boolean *)ptr) = this->UseDragMgrFlagRef();
  211.                     pSize = kABoxUseDragMgrSize;
  212.                     break;
  213.         case    kABoxUseSoundMgr:
  214.                     *((Boolean *)ptr) = this->UseSoundMgrFlagRef();
  215.                     pSize = kABoxUseSoundMgrSize;
  216.                     break;
  217.         case    kABoxIsFinished:
  218.                     *((Boolean *)ptr) = !this->WindowRef();
  219.                     pSize = kABoxIsFinishedSize;
  220.                     break;
  221.         case    kABoxInBackground:
  222.                     *((Boolean *)ptr) = this->IsInBackground();
  223.                     pSize = kABoxInBackgroundSize;
  224.                     break;
  225.         case    kABoxReportMemory:
  226.                     *((Boolean *)ptr) = this->ReportMemoryFlagRef();
  227.                     pSize = kABoxReportMemorySize;
  228.                     break;
  229.         case    kABoxHomeFolder:
  230.                     if (this->HomeFolderRef())
  231.                     {
  232.                         ::BlockMove ((Ptr)this->HomeFolderRef(), ptr, kABoxHomeFolderSize);
  233.                         if (ptrSize)
  234.                             *ptrSize = kABoxHomeFolderSize;
  235.                     } else {
  236.                         error = paramErr;
  237.                     } // end if block
  238.                     break;
  239.         case    kABoxSplashTimeSeconds:
  240.                     *((ABoxSplashTimeType *)ptr) = this->SplashTimeRef();
  241.                     pSize = kABoxSplashTimeSecondsSize;
  242.                     break;
  243.         case    kABoxNumberOfTopics:
  244.                     if (this->TopicsRef())
  245.                         *((ABListCount *)ptr) = this->TopicsRef()->Count();
  246.                     else
  247.                         *((ABIndex *)ptr) = 0;
  248.                     pSize = kABoxNumberOfTopicsSize;
  249.                     break;
  250.         case    kABoxFirstTopicNumber:
  251.                     *((ABIndex *)ptr) = this->FirstTopicRef();
  252.                     *ptrSize = kABoxFirstTopicNumberSize;
  253.                     break;
  254.         case    kABoxCurrentTopic:
  255.                     if (this->TopicsRef())
  256.                         *((ABTopic **)ptr) = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  257.                     else
  258.                         *((ABTopic **)ptr) = NULL;
  259.                     pSize = kABoxCurrentTopicSize;
  260.                     break;
  261.         case    kABoxFirstSlideNumber:
  262.                     *((ABIndex *)ptr) = this->FirstSlideRef();
  263.                     pSize = kABoxFirstSlideNumberSize;
  264.                     break;
  265.         case    kABoxAppResFile:
  266.                     *((short *)ptr) = this->CallerResFileRef();
  267.                     pSize = kABoxAppResFileSize;
  268.                     break;
  269.         case    kABoxUpdater:
  270.                     *((UpdateWindowUPP *)ptr) = this->UpdaterRef();
  271.                     pSize = kABoxUpdaterSize;
  272.                     break;
  273.         case    kABoxModalIndicator:
  274.                     *((ABoxModalIndicator *)ptr) = this->ModalIndicatorRef();
  275.                     pSize = kABoxModalIndicatorSize;
  276.                     break;
  277.         case    kABoxAppNameAndVersion:
  278.                     if (ptr && this->AppNameAndVersionRef())
  279.                         ::BlockMove ((Ptr)this->AppNameAndVersionRef(),
  280.                                     (Ptr)ptr,
  281.                                     kABoxAppNameAndVersionRefSize);
  282.                     pSize = kABoxAppNameAndVersionRefSize;
  283.                     break;
  284.         case    kABoxThreadsHandler:
  285.                     *((DoThreadsUPP *)ptr) = this->ThreadsHandlerRef();
  286.                     pSize = kABoxThreadsHandlerSize;
  287.                     break;
  288.         case    kABoxTextFont:
  289.                     *((ABoxTextFontType *)ptr) = this->TextFontRef();
  290.                     pSize = kABoxTextFontSize;
  291.                     break;
  292.         case    kABoxTextSize:
  293.                     *((ABoxTextSizeType *)ptr) = this->TextSizeRef();
  294.                     pSize = kABoxTextSizeSize;
  295.                     break;
  296.         case    kABoxTextFace:
  297.                     *((ABoxTextFaceType *)ptr) = this->TextFaceRef();
  298.                     pSize = kABoxTextFaceSize;
  299.                     break;
  300.         case    kABoxLastEvent:
  301.                     *((EventRecord *)ptr) = this->LastEventRef();
  302.                     break;
  303.         case    kABoxListHandle:
  304.                     (*(ListHandle *)ptr) = this->ListHandleRef();
  305.                     pSize = kABoxListHandleSize;
  306.                     break;
  307.         case    kABoxWindowTitle:
  308.                     if (!this->WindowNameRef() && this->WindowRef())
  309.                     {
  310.                         this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
  311.                         error = ::MemError();
  312.                         if (error || !this->WindowNameRef())
  313.                             return error;
  314.                         if (this->WindowNameRef() == NULL)
  315.                             return paramErr;
  316.                         ::GetWTitle (this->WindowRef(), this->WindowNameRef());
  317.                     } // end if block
  318.                     
  319.                     if (ptr && this->WindowNameRef())
  320.                         ::BlockMove ((Ptr)this->WindowNameRef(),
  321.                                     (Ptr)ptr,
  322.                                     kABoxWindowTitleSize);
  323.                     pSize = kABoxAppNameAndVersionRefSize;
  324.                     break;
  325.         case    kABoxWindow:
  326.                     *((WindowPtr *)ptr) = this->WindowRef();
  327.                     pSize = kABoxWindowSize;
  328.                     break;
  329.         default:
  330.                     error = kABoxSuperProperty::GetProperty(prop, ptr, ptrSize);
  331.                     break;
  332.     } // end switch block
  333.     
  334.     if (ptrSize && !error)
  335.         *ptrSize = pSize;
  336.         
  337.     return error;
  338.     
  339. } // end GetProperty
  340.  
  341.         
  342.         
  343.         
  344.  
  345. /*=============================== ABox::SetProperty ================================*/
  346. OSErr    ABox::SetProperty (ABProperty prop, void *ptr, long ptrSize)
  347. {
  348.     OSErr            error = noErr;
  349.     const Boolean    resolveAliasChains = true;
  350.     Boolean            targetIsFolder = false,
  351.                     wasAliased = false;
  352.     
  353.     long            pSize;
  354.     //    begin here...
  355.     //
  356.     if (!ptr)
  357.         return kABPropertyNullStorage;
  358.     
  359.     switch (prop)
  360.     {
  361.         case    kABoxIsFinished:
  362.         case    kABoxInBackground:
  363.         case    kABoxWindow:
  364.         case    kABoxListHandle:
  365.         case    kABoxNumberOfTopics:
  366.         case    kABoxCurrentTopic:
  367.                     error = kABPropertyReadOnly;
  368.                     break;
  369.         case    kABoxUseSpeechMgr:
  370.                     this->UseSpeechMgrFlagRef() = *((Boolean *)ptr);
  371.                     pSize = kABoxUseSpeechMgrSize;
  372.                     break;
  373.         case    kABoxUseDragMgr:
  374.                     this->UseDragMgrFlagRef() = *((Boolean *)ptr);
  375.                     pSize = kABoxUseDragMgrSize;
  376.                     break;
  377.         case    kABoxUseSoundMgr:
  378.                     this->UseSoundMgrFlagRef() = *((Boolean *)ptr);
  379.                     pSize = kABoxUseSoundMgrSize;
  380.                     break;
  381.         case    kABoxReportMemory:
  382.                     this->ReportMemoryFlagRef() = *((Boolean *)ptr);
  383.                     break;
  384.         case    kABoxHomeFolder:
  385.                     FSSpec    tFSS;
  386.                     
  387.                     if (!this->HomeFolderRef())
  388.                     {
  389.                         this->HomeFolderRef() = (FSSpecPtr)::NewPtrClear(kABoxHomeFolderSize);
  390.                         error = ::MemError();
  391.                         if (error || !this->HomeFolderRef())
  392.                             return error;
  393.  
  394.                     } // end if block
  395.                     
  396.                     ::BlockMove (ptr, (Ptr)&tFSS, kABoxHomeFolderSize);
  397.                     
  398.                     error = ::ResolveAliasFile (&tFSS, 
  399.                                                 resolveAliasChains, 
  400.                                                 &targetIsFolder, 
  401.                                                 &wasAliased);
  402.                     BlockMove ((Ptr)&tFSS, (Ptr)this->HomeFolderRef(), kABoxHomeFolderSize);
  403.                     break;
  404.         case    kABoxSplashTimeSeconds:
  405.                     this->SplashTimeRef() = *((ABoxSplashTimeType *)ptr);
  406.                     break;
  407.         case    kABoxFirstTopicNumber:
  408.                     this->FirstTopicRef() = *((ABIndex *)ptr);
  409.                     break;
  410.         case    kABoxFirstSlideNumber:
  411.                     this->FirstSlideRef() = *((ABIndex *)ptr);
  412.                     break;
  413.         case    kABoxAppResFile:
  414.                     this->CallerResFileRef() = *((short *)ptr);
  415.                     break;
  416.         case    kABoxUpdater:
  417.                     this->UpdaterRef() = *((UpdateWindowUPP *)ptr);
  418.                     break;
  419.         case    kABoxModalIndicator:
  420.                     this->ModalIndicatorRef() = *((ABoxModalIndicator *)ptr);
  421.                     break;
  422.         case    kABoxAppNameAndVersion:
  423.                     if (!this->AppNameAndVersionRef())
  424.                     {
  425.                         this->AppNameAndVersionRef() = (StringPtr)::NewPtrClear(kABoxAppNameAndVersionRefSize);
  426.                         error = ::MemError();
  427.                         if (error || !this->AppNameAndVersionRef())
  428.                             return error;
  429.                     }
  430.                     ::BlockMove (ptr, (Ptr)this->AppNameAndVersionRef(), *((StringPtr)ptr) + 1);
  431.                     break;
  432.         case    kABoxThreadsHandler:
  433.                     this->ThreadsHandlerRef() = *((DoThreadsUPP *)ptr);
  434.                     break;
  435.         case    kABoxTextFont:
  436.                     this->TextFontRef() = *((ABoxTextFontType *)ptr);
  437.                     break;
  438.         case    kABoxTextSize:
  439.                     this->TextSizeRef() = *((ABoxTextSizeType *)ptr);
  440.                     break;
  441.         case    kABoxTextFace:
  442.                     this->TextFaceRef() = *((ABoxTextFaceType *)ptr);
  443.                     break;
  444.         case    kABoxLastEvent:
  445.                     this->LastEventRef() = *((EventRecord *)ptr);
  446.                     break;
  447.         case    kABoxWindowTitle:
  448.                     if (!this->WindowNameRef())
  449.                     {
  450.                         this->WindowNameRef() = (StringPtr)::NewPtrClear(kABoxWindowTitleSize);
  451.                         error = MemError();
  452.                         if (error || !this->WindowNameRef())
  453.                             return error;
  454.                     }
  455.                     ::BlockMove (ptr, (Ptr)this->WindowNameRef(), *((StringPtr)ptr) + 1);
  456.                     if (this->WindowRef())
  457.                         ::SetWTitle (this->WindowRef(), this->WindowNameRef());
  458.                     break;
  459.         default:
  460.                     error = kABoxSuperProperty::SetProperty(prop, ptr, ptrSize);
  461.                     break;
  462.     } // end switch block
  463.     
  464.     return error;
  465.     
  466. } // end SetProperty
  467.  
  468.  
  469.  
  470.  
  471.  
  472.  
  473.  
  474. /*=============================== ABox::DoThreads ================================*/
  475. //
  476. //    This internal method will allow other threads some time,
  477. //    if need be.
  478. //
  479. OSErr    ABox::DoThreads(void)
  480. {
  481.     //    begin here...
  482.     
  483.     //    adding support for background processing of filters/superfilters via
  484.     //    the thread mechanism.
  485.     //
  486.     
  487.     if (this->ThreadsHandlerRef())
  488.         return CallDoThreadsUpdateProc(this->ThreadsHandlerRef());
  489.     else
  490.         return noErr;
  491.     
  492. } // end DoThreads
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499. /*=============================== ABox::Draw ================================*/
  500. //
  501. //    When envoked, the Draw method will prime the about box and display it
  502. //    for the user. This method will return to the caller, which must then dispatch 
  503. //    events to the about box via the caller's event loop processing.
  504. //
  505. OSErr    ABox::Draw(WindowPtr /*localWindow*/)
  506. {
  507. //#pragma    unused (localWindow)
  508.  
  509.     OSErr            error = noErr;
  510.     
  511.     ABTopic            *topic = NULL;
  512.     Boolean            handled = false;
  513.     GrafPtr            oldPort;
  514.     
  515.     short            itemType;
  516.     Handle            itemHandle;
  517.     Rect            itemRect;
  518.  
  519.     //    begin here...
  520.     //
  521.     if (!this->TopicsRef())
  522.         return paramErr;
  523.     
  524.     ::GetPort (&oldPort);
  525.     
  526.     //    have we been here before?
  527.     if (this->DoesntHaveWindow())
  528.     {
  529.         //    no, so build the about box...
  530.         error = this->BuildABox();
  531.         if (error || this->DoesntHaveWindow())
  532.         {
  533.             //    oops! problems building it, so leave!
  534.             ABERR("\pSorry, error from Build A Box");
  535.             return error;
  536.         } // end if block
  537.     } // end if (!this->WindowRef()) block
  538.     
  539.     ::ShowWindow(this->GetWindow());
  540.         
  541.     if (this->HasWindowNameRef())
  542.         ::SetWTitle (this->GetWindow(), this->WindowNameRef());
  543.         
  544.     this->WindowUpFlagRef() = true;
  545.     this->InBackgroundFlagRef() = false;
  546.     
  547.     if (!error)
  548.     {
  549.         //    we have a valid about box, so draw it...
  550.         topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  551.         if (!topic)
  552.         {
  553.             ABERR("\pSorry, no topic from this->TopicsRef() CurrentLink");
  554.             error = paramErr;
  555.         } else {
  556.             ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  557.             error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  558.  
  559.         } // end if block
  560.     } // end if block
  561.     
  562.     error = this->ChangeControls();
  563.     
  564.     ::SetPort (oldPort);
  565.     
  566.     return error;
  567.     
  568. } // end Draw
  569.  
  570.  
  571.  
  572.  
  573.  
  574. /*=============================== ABox::BuildABox ================================*/
  575. //
  576. //    When envoked, the BuildABox internal method will prime the about box 
  577. //    by loading the this->TopicsRef(), creating the list, setting up the default dialog
  578. //    items, etc.
  579. //
  580. OSErr    ABox::BuildABox (void)
  581. {
  582.     OSErr            error = noErr;
  583.     UserItemUPP        theUPP;
  584.     short            itemType;
  585.     Handle            itemHandle;
  586.     Rect            itemRect;
  587.     short            fontHeight;
  588.     short            adjustment;
  589.     GrafPtr            oldPort;
  590.  
  591.     ABUEnvDialog    *dialogEnv = NULL;
  592.     ABTopic            *topic = NULL;
  593.     
  594.     Cell            firstCellToShow;
  595.  
  596.     //    begin here...
  597.     
  598.     
  599.     //    try and load the dialog box...
  600.     ::GetPort (&oldPort);
  601.     if (this->SplashTimeRef() == kABoxWaitForApplicationSplash)
  602.         this->ModalIndicatorRef() = kABoxMoveableModal;
  603.         
  604.     switch (this->ModalIndicatorRef())
  605.     {
  606.         case    kABoxMoveableModal:
  607.                 this->DialogIDRef() = kABmoveableModalDialog;
  608.                 break;
  609.         case    kABoxModeless:    
  610.                 this->DialogIDRef() = kABmodelessDialog; 
  611.                 break;
  612.         case    kABoxModal:
  613.         default:
  614.                 this->DialogIDRef() = kABmodalDialog; 
  615.                 break;
  616.     } // end switch block
  617.     this->WindowRef() = ::GetNewDialog (this->DialogIDRef(), kABallocateDialogRecordStorage, kABdialogInFront);
  618.     error = ::ResError();
  619.     if (error || this->DoesntHaveWindow()) 
  620.     {
  621.         //    the attempt to load the dialog resource failed.
  622.         ::SetPort (oldPort);
  623.         return error;
  624.     } // end if block
  625.     
  626.     //    initialize here...
  627.     ::SetPort (this->GetWindow());
  628.  
  629.     //    set up the text stuff...
  630.     //
  631.     ::TextFont(this->TextFontRef());
  632.     ::TextSize(this->TextSizeRef());
  633.     ::TextFace(this->TextFaceRef());
  634.     //    set the procedure pointer for the user items in the dialog.
  635.     //
  636.     //    Before you display the dialog box, use the SetDialogItem procedure to install 
  637.     //    this procedure in the dialog record. Before using SetDialogItem, you must first 
  638.     //    use the GetDialogItem procedure to obtain a handle to an item of type userItem.
  639.     //    If you enable the application-defined item that you draw with this procedure, 
  640.     //    the ModalDialog procedure and the DialogSelect function return the item’s number 
  641.     //    when the user clicks that item.
  642.     //
  643.     //ABoxDebugNew();
  644.     theUPP = NewUserItemProc(DrawDialogItem);
  645.     ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  646.     ::SetDItem(this->GetWindow(), kAboutBoxSlideField, itemType, (Handle)theUPP, &itemRect);
  647.  
  648.     ::GetDItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
  649.     
  650.     //    calculate the "correct" size for the list based upon the
  651.     //    dialog's font characteristics.
  652.     //
  653.     fontHeight = ABUFonts::FindFontHeight();
  654.     //adjustment = (itemRect.bottom - itemRect.top - 2 * kABbezelShades) % fontHeight;
  655.     adjustment = (itemRect.bottom - itemRect.top) % fontHeight;
  656.  
  657.     //    give the list a nice interval to work with, allowing the slack to go to or
  658.     //    come from the app and version area
  659.     //
  660.     itemRect.bottom += adjustment;
  661.     ::SetDItem(this->GetWindow(), kAboutBoxTopic, itemType, (Handle)theUPP, &itemRect);
  662.     
  663.     //    make the modifications to the kAboutBoxAppAndVersion dialog
  664.     //    item to compensate for fiddling with the kAboutBoxTopic item.
  665.     //
  666.     ::GetDItem(this->GetWindow(), kAboutBoxAppAndVersion, &itemType, &itemHandle, &itemRect);
  667.     itemRect.top += adjustment;
  668.     ::SetDItem(this->GetWindow(), kAboutBoxAppAndVersion, itemType, (Handle)theUPP, &itemRect);
  669.  
  670.     dialogEnv = new ABUEnvDialog;
  671.     if (dialogEnv)
  672.     {
  673.         if (dialogEnv->IsPresent())
  674.         {
  675.             error = ::SetDialogDefaultItem(this->GetWindow(), kAboutBoxOK);
  676.             error = ::SetDialogCancelItem(this->GetWindow(), kAboutBoxOK);
  677.             error = ::SetDialogTracksCursor(this->GetWindow(), false);
  678.         } // end if block
  679.         delete dialogEnv;
  680.     } // end if block
  681.     
  682.     //    push this object into the refCon of the dialog box so we can
  683.     //    allow the dialog manager routines access
  684.     //
  685.     ::SetWRefCon(this->GetWindow(), (long) this);
  686.  
  687.     error = this->TopicsRef()->Load(this->HomeFolderRef(), this->CallerResFileRef());
  688.     if (error)
  689.     {
  690.         ABERR("\pSorry, error from this->TopicsRef() Load(this->HomeFolderRef())");
  691.         return error;
  692.     } // end if block
  693.     
  694.     error = this->CreateAndFillTopicList();
  695.     if (error)
  696.     {
  697.         ABERR("\pSorry, error from CreateAndFillTopicList");
  698.         return error;
  699.     } // end if block
  700.     
  701.     
  702.     //    select the "first" topic, whichever one that might really be...
  703.     ::SetPt (&firstCellToShow, 0, this->FirstTopicRef() - 1);
  704.     ::LSetSelect (true, firstCellToShow, this->ListHandleRef());
  705.     
  706.     topic = (ABTopic *)this->TopicsRef()->GotoLink (this->FirstTopicRef());
  707.     if (!topic)
  708.         return paramErr;
  709.     else
  710.         error = topic->GotoSlide (this->FirstSlideRef());
  711.  
  712.  
  713.     return error;
  714. } // end BuildABox
  715.  
  716.  
  717.  
  718.  
  719.  
  720.  
  721. /*=============================== CreateAndFillTopicList ===============================*/
  722. //
  723. //    this function will perform the list creation and population.
  724. //
  725. //    the function returns an OSErr to indicate any errors.
  726. //
  727. //
  728. //    is called by:
  729. //        DoAbout
  730. //
  731. OSErr    ABox::CreateAndFillTopicList (void)
  732. {
  733.     OSErr                error = noErr;
  734.     
  735.     //    these items are for the geometry of the List
  736.     short                itemType;
  737.     Handle                itemHandle;
  738.     Rect                itemRect;
  739.  
  740.     //    these items are used to build the List
  741.     Rect                dataBounds;                    // the dimensions of the data in the list
  742.     Point                cellSize;                    // width and height of a cells rectangle
  743.     Point                cell;                        // an index through the list
  744.     long                numberOfTopics;
  745.     ListClickLoopUPP    clickLoopUPP = NULL;
  746.     
  747.     //    these items are used in the actual cell construction
  748.     //    for the list
  749.     short                i, index;
  750.     long                topicDepth;
  751.     ABTopic                *topic;
  752.  
  753.     //    these items are used to determine the pseudo-user
  754.     //    name in the list
  755.     StringHandle        userName;
  756.     Str255                topicName;
  757.     Str255                youFile,
  758.                         temp;
  759.     Boolean                sameString = false;
  760.     
  761.     
  762.     //    begin..
  763.     //
  764.  
  765.     //-------------------------------
  766.     //
  767.     //    now let's create the list to hold the various this->TopicsRef().
  768.     //
  769.     ::GetDItem(this->GetWindow(), kAboutBoxTopic, &itemType, &itemHandle, &itemRect);
  770.  
  771.     //    make room for topic list's scroll bars (see IM IV-270)
  772.     this->DrawFrame (itemRect);
  773.      itemRect.right -= kABscrollBarWidth;
  774.  
  775.     //    create a list
  776.     //
  777.     numberOfTopics = this->TopicsRef()->Count();
  778.     ::SetRect (&dataBounds, 0, 0, 1, (short)numberOfTopics);
  779.     
  780.     //    let the list manager determine the best size
  781.     ::SetPt (&cellSize, 0, 0);
  782.     
  783.     //    create the list
  784.     //ABoxDebugNew();
  785.     this->ListHandleRef() = ::LNew(&itemRect,            //    view rectangle
  786.                 &dataBounds,                        //    dimensions of the list
  787.                 cellSize,                            //    size of the cells
  788.                 0,                                    //    procID to use
  789.                 this->GetWindow(),                    //    containing window
  790.                 //true,                                //    drawIt
  791.                 false,                                //    drawIt
  792.                 false,                                //    hasGrow box
  793.                 false,                                //    horizontal scroll?
  794.                 true);                                //    vertical scroll?
  795.     if (!this->ListHandleRef())
  796.     {
  797.         //    couldn't create a list...
  798.         error = paramErr;
  799.         //ABoxDebug(kABErrBadArgListHandle, error);
  800.         return error;
  801.     }    //    end if block
  802.  
  803.  
  804.     //    set the selection flags which determine how the user
  805.     //    can select items in the list
  806.     (*this->ListHandleRef())->selFlags = lOnlyOne | lNoExtend | lNoRect | lNoNilHilite;
  807.  
  808.     //    initialize the List's cell's contents with the names of the this->TopicsRef()
  809.     //    from the topic list
  810.     //error = GetUsername (userName);
  811.     userName = ::GetString (kABownerNameString);
  812.     ::GetIndString (youFile, kABStrings, kAByourNameHereFile);
  813.     
  814.     //    Our list is a one-dimensional object, but since
  815.     //    List Mgr lists support rows and columns, i'll contruct
  816.     //    the building-loop to support multiple columns even
  817.     //    though i'm only concerned with a single column list.
  818.     //    This will make it easier in the future if I were
  819.     //    to change how the list is displayed.
  820.     //
  821.     index = 1;
  822.     for (cell.v = 0; cell.v < (**this->ListHandleRef()).dataBounds.bottom; ++cell.v) 
  823.     {
  824.         for (cell.h = 0; cell.h < (**this->ListHandleRef()).dataBounds.right; ++cell.h) 
  825.         {
  826.             topic = (ABTopic *)this->TopicsRef()->NthLink(index);
  827.             if (!topic)
  828.             {
  829.                 ++index;
  830.                 continue;
  831.             } // end if block
  832.             
  833.             error = topic->GetProperty (kABTopicName, &topicName, NULL);
  834.             error = topic->GetProperty (kABTopicDepth, &topicDepth, NULL);
  835.             
  836.             if (topicName[0] != 0) 
  837.             {
  838.                 //    pad the topic name to simulate indented this->TopicsRef() based
  839.                 //    upon the "depth" of the topic.
  840.                 //
  841.                 temp[0] = 0;
  842.                 for (i = 0; i < topicDepth; i++)
  843.                     ABUString::P2Pstrcat( temp, "\p  " );
  844.             
  845.                 sameString = ::EqualString (topicName, 
  846.                                             youFile, 
  847.                                             kABcaseSensitive,
  848.                                             kABdiacriticalSensitive);
  849.                 if (sameString && !error) 
  850.                 {
  851.                     //    we are now looking at the dummy file "you",
  852.                     //    so we'll substitute the Sharing Setup control
  853.                     //    panel's default owner/user name here if possible.
  854.                     //
  855.                     ::HLock ((Handle)userName);
  856.                     ABUString::P2Pstrcat (temp, *userName);
  857.                     ::HUnlock ((Handle)userName);
  858.                     
  859.                 } else {
  860.                     ABUString::P2Pstrcat (temp, topicName);
  861.                     
  862.                     //    not the dummy file, so continue...
  863.                 }    //    end if else block
  864.                 
  865.                 //    initialize the cell contents to this string.
  866.                 //
  867.                 ::LSetCell(&temp[1],
  868.                         temp[0],
  869.                         cell,
  870.                         this->ListHandleRef());
  871.             } // end if block
  872.             
  873.             index++;
  874.             
  875.         }    // end of for(cell.h) loop to actually assign the cell values
  876.     }    // end of for(cell.v) loop to index the cell values
  877.     ::LDoDraw (true, this->ListHandleRef());
  878.     return error;
  879.  
  880. }    //    end of function CreateAndFillTopicList()
  881.  
  882.  
  883.  
  884.  
  885.  
  886.  
  887. /*=============================== ABox::DrawDialogItem ===============================*/
  888. //
  889. //    this function will handle the re/drawing of the various custom
  890. //    items in the dialog box
  891. //
  892. //    from Toolbox Essentials, p. 6-143:
  893. //
  894. //    Application-Defined Routines
  895. //    If you supply an application-defined item in a dialog box, you must provide a 
  896. //    draw procedure for the Dialog Manager to use when displaying the item; that 
  897. //    procedure is referred to in this section as MyItem. If you want the Dialog 
  898. //    Manager to play sounds other than the system alert sound, you must provide your 
  899. //    own sound procedure, referred to in this section as MyAlertSound. To supplement 
  900. //    the Dialog Manager’s ability to handle events in the Macintosh multitasking 
  901. //    environment, you should provide an event filter function that the Dialog Manager 
  902. //    calls whenever it displays alert boxes and modal dialog boxes. This function is 
  903. //    referred to as MyEventFilter.
  904. //    
  905. //    MyItem
  906. //    To draw your own application-defined item in a dialog box, provide a draw 
  907. //    procedure that takes two parameters: a window pointer to the dialog box and an 
  908. //    item number from the dialog box’s item list resource. For example, this is how 
  909. //    you should declare the procedure if you were to name it MyItem:
  910. //    
  911. //
  912. //    PROCEDURE MyItem (theWindow: WindowPtr; itemNo: Integer);
  913. //        theWindow    A pointer to the dialog record for the dialog box containing
  914. //                    an application-defined item. If your procedure can draw in
  915. //                    more than one dialog box, this parameter tells your procedure
  916. //                    which one to draw in.
  917. //    
  918. //        itemNo        A number corresponding to the position of an item in the item 
  919. //                    list resource for the specified dialog box. If your procedure  
  920. //                    draws more than one item, this parameter tells your procedure  
  921. //                    which one to draw.
  922. //    
  923. //    The Dialog Manager calls your procedure to draw an application-defined item at 
  924. //    the time you display the specified dialog box. When calling your draw procedure, 
  925. //    the Dialog Manager sets the current port to the dialog box’s graphics port. 
  926. //    Normally, you create an invisible dialog box and then use the Window Manager 
  927. //    procedure ShowWindow to display the dialog box.
  928. //    
  929. //    Before you display the dialog box, use the SetDialogItem procedure to install 
  930. //    this procedure in the dialog record. Before using SetDialogItem, you must first 
  931. //    use the GetDialogItem procedure to obtain a handle to an item of type userItem.
  932. //    If you enable the application-defined item that you draw with this procedure, 
  933. //    the ModalDialog procedure and the DialogSelect function return the item’s number 
  934. //    when the user clicks that item. If your application needs to respond to a user 
  935. //    action more complex than this (for example, if your application needs to measure 
  936. //    how long the user holds down the mouse or how far the user drags the cursor), 
  937. //    your application must track the cursor itself. If you use ModalDialog, your event 
  938. //    filter function must handle events inside the item; if you use DialogSelect, your 
  939. //    application must handle events inside the item before handing events to DialogSelect.
  940. //    
  941. //
  942. //    is called by:
  943. //        the dialog manager
  944. //
  945. pascal void ABox::DrawDialogItem(DialogPtr dialog, short itemNo)
  946. {
  947.     short                itemType;
  948.     Handle                itemHandle;
  949.     Rect                itemRect;
  950.     
  951.     OSErr                error = noErr;
  952.     ABox                *abox;
  953.     ABTopic                *topic;
  954.     ListHandle            listHandle = NULL;
  955.     Str255                appName;
  956.     Boolean                inBackground = false;
  957.     ABoxSplashTimeType    splash;
  958.     
  959.     //    begin here...
  960.     
  961.     abox = (ABox *)::GetWRefCon(dialog);
  962.     if (!abox)
  963.         return;
  964.     
  965.     error = abox->GetProperty(kABoxCurrentTopic, &topic, NULL);
  966.     if (error)
  967.         return;
  968.  
  969.     error = abox->GetProperty(kABoxInBackground, &inBackground, NULL);
  970.     if (error)
  971.         return;
  972.         
  973.     error = abox->GetProperty(kABoxSplashTimeSeconds, &splash, NULL);
  974.     if (error)
  975.         return;
  976.         
  977.     ::GetDItem(dialog, itemNo, &itemType, &itemHandle, &itemRect);
  978.  
  979.     switch(itemNo) 
  980.     {
  981.     
  982.         case kAboutBoxTopic :
  983.     
  984.             //    recover the list handle.
  985.             //
  986.             error = abox->GetProperty(kABoxListHandle, &listHandle, NULL);
  987.             if (!error && listHandle) 
  988.             {
  989.                 
  990.                 //    draw the list's framing rectangle OUTSIDE the view rectangle.
  991.                 //    if the frame is drawn inside the view rectangle then these lines
  992.                 //    will be erased, drawn onto or scrolled by the List Manager since 
  993.                 //    the lines are within the rectangle LM expects to be able to draw in.
  994.                 //
  995.                 //    let the List Manager draw the list
  996.                 ::LUpdate (dialog->visRgn, listHandle);
  997.                 
  998.             }    //    end if block
  999.             
  1000.             abox->DrawFrame (itemRect);
  1001.             break;
  1002.         
  1003.         case    kAboutBoxAppAndVersion:
  1004.                 abox->DrawFrame(itemRect);
  1005.                 error = abox->GetProperty(kABoxAppNameAndVersion, &appName, NULL);
  1006.                 if (!error)
  1007.                 {
  1008.                     ::InsetRect(&itemRect, 1, 1);
  1009.                     error = ABUTextBox::DrawTextBox ((unsigned char *)&(abox->AppNameAndVersionRef()[1]), 
  1010.                                             (unsigned long) (abox->AppNameAndVersionRef()[0]), 
  1011.                                             &itemRect,
  1012.                                             kNTBJustFull, 
  1013.                                             0, 
  1014.                                             NULL, 
  1015.                                             NULL);
  1016.                 }
  1017.             break;
  1018.             
  1019.         case    kAboutBoxSlideField:
  1020.             if (topic) 
  1021.             {
  1022.                 error = topic->Update(dialog);
  1023.             } // end if block
  1024.             break;
  1025.         
  1026.     }    //    end of switch block...
  1027.     
  1028.     return;
  1029.     
  1030. }    //    end of function DrawDialogItem()
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036. /*=============================== ABox::Update ================================*/
  1037. OSErr    ABox::Update(WindowPtr /*window*/)
  1038. {
  1039.     OSErr    error = noErr;
  1040.     
  1041.     ABTopic        *topic;
  1042.     
  1043.     //    begin here...
  1044.     //
  1045.     if (!this->TopicsRef())
  1046.         return error;
  1047.     
  1048.     topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1049.     if (topic)
  1050.         error = topic->Update(this->GetWindow());
  1051.  
  1052.     return error;
  1053.     
  1054. } // end Update
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061. /*=============================== ABox::Splash ================================*/
  1062. //
  1063. //    return "true" to indicate that the splash is complete and that the abox
  1064. //        should be torn down.
  1065. //
  1066. //    return "false" to indicate that the splash is not complete, but don't interact
  1067. //        with either.
  1068. //
  1069. Boolean    ABox::Splash (EventRecord *eventRec)
  1070. {
  1071.     Boolean            splashDown = false;
  1072.     OSErr            error = noErr;
  1073.     GrafPtr            oldPort;
  1074.     static long        localTimer = 0;
  1075.     
  1076.     //    begin here...
  1077.     
  1078.     if (this->IsNotSplashScreen())
  1079.         return splashDown = false;
  1080.         
  1081.     if (localTimer == 0)
  1082.         localTimer = TickCount();
  1083.         
  1084.     ::GetPort (&oldPort);
  1085.     ::SetPort (this->GetWindow());
  1086.     
  1087.     if (this->WindowIsntUp())
  1088.     {
  1089.         ::ShowWindow(this->GetWindow());
  1090.         ::SelectWindow(this->GetWindow());
  1091.         error = this->CheckAllControls (this->GetWindow(), false);
  1092.         this->WindowUpFlagRef() = true;
  1093.     } // end if block
  1094.  
  1095.     error = this->CheckAllControls (this->GetWindow(), false);
  1096.     error = this->ChangeControls();
  1097.     
  1098.     switch (this->SplashTimeRef())
  1099.     {
  1100.         case    kABoxWaitForClickSplash:
  1101.                 //    wait for the user to click or keypress
  1102.                 //    before going away...
  1103.                 if (eventRec)
  1104.                     splashDown = ((eventRec->what == keyDown) || 
  1105.                                     (eventRec->what == autoKey) || 
  1106.                                     (eventRec->what == mouseDown));
  1107.                 localTimer = 0;
  1108.                 break;
  1109.         case    kABoxWaitForApplicationSplash:
  1110.                 //    do nothing except sit there...the application will
  1111.                 //    tear us down when it's good and ready...
  1112.                 splashDown = false;
  1113.                 localTimer = 0;
  1114.                 break;
  1115.         default:
  1116.                 //    the caller has specified a timed splash screen,
  1117.                 //    so splash we will...
  1118.                 splashDown = (::TickCount() - localTimer) >= (60 * this->SplashTimeRef());
  1119.                 break;
  1120.     } // end switch block
  1121.     
  1122.     if (splashDown)
  1123.         localTimer = 0;
  1124.     ::SetPort (oldPort);
  1125.     return splashDown;
  1126. } // end Splash
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132. /*=============================== ABox::Event ================================*/
  1133. //
  1134. //    ALL INITIAL EVENT HANDLING is focused here...
  1135. //
  1136. //    if the abox is modal, then we hand off to a loop of ModalDialog()
  1137. //        via the ModalEvent() method.
  1138. //
  1139. //    if the abox is modeless, then we determine if the event belongs to
  1140. //        the abox dialog, and process accordingly.
  1141. //
  1142. //    if the abox is movable modal, then we do that too.
  1143. //
  1144. Boolean    ABox::Event(EventRecord *eventRec)
  1145. {
  1146.     Boolean            handled = false;
  1147.     Boolean            handledIt = false;
  1148.     OSErr            error = noErr;
  1149.     short            itemNo = 0;
  1150.     DialogPtr        dialog = NULL;
  1151.     GrafPtr            oldPort;
  1152.     
  1153.     unsigned long    localSleep = 5;
  1154.             
  1155.     //    begin here...
  1156.     //
  1157.     
  1158.     ::GetPort (&oldPort);
  1159.     if (this->DoesntHaveWindow() || this->WindowIsntUp())
  1160.         return false;
  1161.         
  1162.     ::SetPort (this->GetWindow());
  1163.     
  1164.     if (! this->IsModal()) 
  1165.     {
  1166.         if (!eventRec)
  1167.             return handled = false;
  1168.         
  1169.         //    check the caller's requested splash configuration...
  1170.         if (this->Splash(eventRec))
  1171.         {
  1172.             error = this->Close();
  1173.             return true;
  1174.         } // end if block
  1175.  
  1176.         handledIt = CallModalFilterProc(this->ModalUPPRef(), this->GetWindow(), eventRec, &itemNo);
  1177.  
  1178.         handled = this->HandleEvent(eventRec, itemNo);
  1179.         if (itemNo == kAboutBoxOK) 
  1180.         {
  1181.             //    sigh. the "OK" button has been clicked. Bye bye...
  1182.             error = this->Close();
  1183.             handled = true;
  1184.         } // end if block
  1185.         
  1186.     } else {
  1187.         //    this the stock ModalDialog
  1188.         
  1189.         do 
  1190.         {
  1191.             ::ModalDialog(this->ModalUPPRef(), &itemNo);
  1192.                 
  1193.             //    check the caller's requested splash configuration...
  1194.             if (itemNo != kAboutBoxOK) {
  1195.                 //    Take action on the item hit by the user...
  1196.                 (void)this->HandleEvent (&(this->LastEventRef()), itemNo);
  1197.             } // end if block
  1198.             
  1199.         } while (itemNo != kAboutBoxOK);
  1200.         
  1201.         this->WindowUpFlagRef() = false;
  1202.         error = this->Close();
  1203.         handled = true;
  1204.     }    // end if else block
  1205.     
  1206.     ::SetPort (oldPort);
  1207.     
  1208.     return handled;
  1209.     
  1210. } // end Event
  1211.  
  1212.  
  1213.  
  1214.  
  1215.  
  1216. /*=============================== ABox::HandleEvent ================================*/
  1217. //
  1218. //    HandleEvent is used to perform the bulk of all event processing for
  1219. //    the About Box, whether it is running as a modal dialog, a modeless
  1220. //    dialog, or even possibly just as a window.
  1221. //
  1222. //    If the abox is processing things via ModalDialog, the itemNo
  1223. //    set within the modal dialog filter (ModalDialogEventFilter in our
  1224. //    case) and the event are sent directly to here before leaving
  1225. //    ModalDialog.
  1226. //
  1227. //    If the abox is processing things in a non-modal (a-modal?) fashion,
  1228. //    then the Event method has received the event, determined what (if any)
  1229. //    item the user has interacted with, and sent the information here
  1230. //    for processing. 
  1231. //
  1232. Boolean    ABox::HandleEvent (EventRecord *event, short itemNo)
  1233. {
  1234.     Boolean        eventHandled = false;
  1235.     OSErr        error = noErr;
  1236.     
  1237.     ABTopic        *topic = NULL;
  1238.     WindowPtr    curWindow = NULL;
  1239.     short        clickArea;
  1240.     
  1241.     //    begin here...
  1242.     
  1243.     switch (event->what)
  1244.     {
  1245.         case mouseDown:
  1246.             if (this->IsSplashScreen())
  1247.                 return eventHandled;
  1248.                 
  1249.             if (! this->IsModal())
  1250.             {
  1251.                 clickArea = ::FindWindow (event->where, &curWindow);
  1252.  
  1253.                 //    now process the event...
  1254.                 switch (clickArea)
  1255.                 {
  1256.                     case    inDesk:
  1257.                     case    inSysWindow:
  1258.                         //    the click was _outside_ of this application
  1259.                         //    so shove the abox to the background...
  1260.                         this->ToBackground();
  1261.                         eventHandled = false;
  1262.                         break;
  1263.                     case    inDrag:
  1264.                         if (this->NotOurWindow(curWindow))
  1265.                         {
  1266.                             if (this->IsMoveableModal())
  1267.                             {
  1268.                                 //    sorry, can't select a back window (in this app)
  1269.                                 //    when a modal type dialog is up.
  1270.                                 ABERR("\psorry, you can't drag another window while moadal.");
  1271.                                 eventHandled = true;
  1272.                             } else {
  1273.                                 //    let the other event loop handler deal with
  1274.                                 //    this; we'll just prepare to go to the back
  1275.                                 eventHandled = false;
  1276.                                 this->ToBackground();
  1277.                             } // end if block
  1278.                         } else {
  1279.                             //    we are the window being dragged...let the
  1280.                             //    main application loop handle us
  1281.                             if (this->NotTheFrontWindow())
  1282.                                 //    1.0.4 ty -- checks for bringing to the foreground
  1283.                                 this->ToForeground();
  1284.                             eventHandled = false;
  1285.                         } // end if else block
  1286.  
  1287.                         break;
  1288.                     case    inContent:
  1289.                         //    track the event, so to speak...
  1290.                         
  1291.                         if (this->NotOurWindow(curWindow))
  1292.                         {
  1293.                             if (this->IsMoveableModal())
  1294.                             {
  1295.                                 //    sorry, can't select a back window (in this app)
  1296.                                 //    when a modal type dialog is up.
  1297.                                 ABERR("\psorry, you can't select another window's contents while moadal.");
  1298.                                 eventHandled = true;
  1299.                             } else {
  1300.                                 //    let the other event loop handler deal with
  1301.                                 //    this; we'll just prepare to go to the back
  1302.                                 eventHandled = false;
  1303.                                 this->ToBackground();
  1304.                             } // end if block
  1305.                         } else {
  1306.                             if (this->NotTheFrontWindow())
  1307.                                 //    1.0.3 ty -- checks for bringing to the foreground
  1308.                                 this->ToForeground();
  1309.                             error = this->ProcessItemHit (event, itemNo);
  1310.                             eventHandled = (error) ? false : true;
  1311.                         } // end if else block
  1312.                         break;
  1313.                     default:
  1314.                         eventHandled = false;
  1315.                 } // end switch (clickArea)
  1316.             } else {
  1317.                 //    a modal dialog also needs to process the events...
  1318.                 error = this->ProcessItemHit (event, itemNo);
  1319.             } // end if block
  1320.             break;
  1321.             
  1322.         case activateEvt:
  1323.             //    we were either activated or deactivated...
  1324.             curWindow = (WindowPtr)(event->message);
  1325.             eventHandled = false;
  1326.             if (this->NotOurWindow(curWindow))
  1327.             {
  1328.                 if (event->modifiers & activeFlag)
  1329.                     //    some other window is being activated,
  1330.                     //    and this event doesn't belong to us, so
  1331.                     //    move to the background...
  1332.                     this->ToBackground();
  1333.             } else if (!this->IsModal()) {
  1334.                 if (event->modifiers & activeFlag)
  1335.                 {
  1336.                     if (this->NotTheFrontWindow())
  1337.                         this->ToForeground();
  1338.                 } else {
  1339.                     this->ToBackground();
  1340.                 } // end if else block
  1341.                 
  1342.             } // end if else block
  1343.             break;
  1344.     
  1345.         case osEvt:
  1346.             //    we're talking major league context switch here gang...
  1347.             //    
  1348.             switch ((event->message >> 24) & 0xFF) 
  1349.             {
  1350.             //    Must logical and with 0xFF to get only low byte.
  1351.             //    High byte of message
  1352.                 case    mouseMovedMessage:
  1353.                         //    big deal, huh?
  1354.                         break;
  1355.                 case    suspendResumeMessage:
  1356.                         // layer switch
  1357.                         if(event->message & resumeFlag)
  1358.                         {
  1359.                             //    switch into the foreground...
  1360.                             if (this->IsTheFrontWindow())
  1361.                                 this->ToForeground();
  1362.                         } else {
  1363.                             //    switch into the background...
  1364.                                 this->ToBackground();
  1365.                         }
  1366.                         break;
  1367.             } // end switch block
  1368.  
  1369.             //    allow the main event loop to process this
  1370.             //    event as well by returning false
  1371.             eventHandled = false;
  1372.             break;
  1373.             
  1374.         default:
  1375.             eventHandled = false;
  1376.             break;
  1377.             
  1378.     } // end switch block
  1379.     
  1380.     if (this->ReportMemoryFlagRef())
  1381.         this->ReportMemory();
  1382.     
  1383.     return eventHandled;
  1384. } // end HandleEvent()
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390. /*=============================== ABox::ToBackground ===============================*/
  1391. OSErr    ABox::ToBackground (void)
  1392. {
  1393.     OSErr        error = noErr;
  1394.     ListHandle    lh = this->ListHandleRef();
  1395.     
  1396.     //    begin here...
  1397.     if (this->IsInForeground())
  1398.     {
  1399.         this->InBackgroundFlagRef() = true;
  1400.         error = this->SaveControlStates (this->GetWindow());
  1401.         error = this->CheckAllControls (this->GetWindow(), this->IsInForeground());
  1402.         
  1403.         //    1.0.7 ty...addition to deactivate the list here
  1404.         //                when moving to the background.
  1405.         //
  1406.         if (lh)
  1407.             ::LActivate (false, lh);
  1408.             
  1409.     } // end if block
  1410.     
  1411.     return error;
  1412. } // end ToBackground
  1413.  
  1414.  
  1415.  
  1416.  
  1417. /*=============================== ABox::ToForeground ===============================*/
  1418. OSErr    ABox::ToForeground (void)
  1419. {
  1420.     OSErr        error = noErr;
  1421.     ListHandle    lh = this->ListHandleRef();
  1422.     
  1423.     //    begin here...
  1424.     if (this->IsInBackground())
  1425.     {
  1426.         this->InBackgroundFlagRef() = false;
  1427.         ::SelectWindow(this->GetWindow());
  1428.         ::SetPort (this->GetWindow());
  1429.         error = this->RestoreControlStates (this->GetWindow());
  1430.         //    1.0.7 ty...addition to activate the list here
  1431.         //                when moving to the background.
  1432.         //
  1433.         if (lh)
  1434.             ::LActivate (true, lh);
  1435.             
  1436.     } // end if block
  1437.     
  1438.     return error;
  1439. } // end ToForeground
  1440.  
  1441.  
  1442.  
  1443.  
  1444.  
  1445.  
  1446. /*=============================== ABox::ProcessItemHit ===============================*/
  1447. OSErr    ABox::ProcessItemHit (EventRecord *event, short itemNo)
  1448. {
  1449.     OSErr            error = noErr;
  1450.     Point            where;
  1451.     Cell            cell;
  1452.     ABTopic            *topic;
  1453.     Boolean            ok = false;
  1454.     
  1455.     short            itemType;
  1456.     Handle            itemHandle;
  1457.     Rect            itemRect;
  1458.  
  1459.     short            topicIndex;
  1460.     GrafPtr            oldPort;
  1461.     
  1462.     //    begin here...
  1463.     
  1464.     if (!event)
  1465.         return paramErr;
  1466.         
  1467.     if ((event->what != mouseDown) && 
  1468.         (event->what != keyDown) &&
  1469.         (event->what != autoKey))
  1470.         return error;
  1471.     
  1472.     //    get the old port
  1473.     ::GetPort (&oldPort);
  1474.     ::SetPort (this->GetWindow());
  1475.     
  1476.     where = event->where;
  1477.     ::GlobalToLocal(&where);
  1478.     
  1479.     ::GetDItem(this->GetWindow(), kAboutBoxSlideField, &itemType, &itemHandle, &itemRect);
  1480.  
  1481.     switch (itemNo) 
  1482.     {
  1483.         //    now check the value of itemNo (if the event hasn't been handled)
  1484.         //
  1485.         case    kAboutBoxAppAndVersion:
  1486.         case    kAboutBoxSlideField:
  1487.             break;
  1488.         case    kAboutBoxPrevButton:
  1489.         case    kAboutBoxNextButton:
  1490.             if (!this->IsControlActive(GetControlHandle (this->GetWindow(), itemNo)))
  1491.                 break;
  1492.                 
  1493.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1494.             if (topic)
  1495.             {
  1496.                 if (itemNo == kAboutBoxPrevButton)
  1497.                     //    back up one slide in the current slide list
  1498.                     //    for the current topic
  1499.                     //
  1500.                     error = topic->PreviousSlide();
  1501.                 else
  1502.                     //    advance to the next slide in the current list.
  1503.                     //
  1504.                     error = topic->NextSlide();
  1505.                 
  1506.                 error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1507.             } // end if block
  1508.             break;
  1509.             
  1510.         case    kAboutBoxPlayButton:
  1511.             //
  1512.             //    addition of the play button to replay the
  1513.             //        controller-less movie or the sound.
  1514.             //
  1515.             if (!this->IsControlActive(this->GetControlHandle (this->GetWindow(), itemNo)))
  1516.                 break;
  1517.  
  1518.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1519.             if (topic)
  1520.             {
  1521.                 //    ok, we've got the current topic. Now we'll examine
  1522.                 //    it to see if it is a playable thing, which would
  1523.                 //    be (a) a movie topic without a controller or (b) a
  1524.                 //    sound element of the current slide
  1525.                 //
  1526.                 
  1527.                 Boolean    playableMovie = false;
  1528.                 
  1529.                 //    check to see if the topic _is_ a movie...
  1530.                 error = topic->GetProperty (kABTopicHasMovieController, &playableMovie, NULL);
  1531.                 if (!error && !playableMovie)
  1532.                 {
  1533.                     //    it _is_ a movie without a controller
  1534.                     //    stop the current activity in its tracks
  1535.                     error = topic->Stop();
  1536.                     topic->Draw(this->GetWindow());
  1537.                 } else {
  1538.                     //    ok, it's not a movie...does it have a sound?
  1539.                     
  1540.                     ABSlide    *cSlide = topic->CurrentSlide();
  1541.                     if (cSlide)
  1542.                     {
  1543.                         //    yes, there is a current slide...does it have
  1544.                         //    a sound element?
  1545.                         //
  1546.                         ABSound    *aSound = (ABSound *)cSlide->GetResourceOfType(kABSoundResource);
  1547.                         
  1548.                         if (aSound)
  1549.                         {
  1550.                             //    stop the current activity in its tracks
  1551.                             error = aSound->Stop();
  1552.                             //    tell the sound to replay itself...
  1553.                             aSound->Draw(this->GetWindow());
  1554.                         } // end if block
  1555.                     } // end if cSlide;
  1556.                     
  1557.                 } // end if block
  1558.             } // end if block
  1559.             break;
  1560.         
  1561.         case    kAboutBoxTopic:
  1562.             //    the user clicked in the List
  1563.             //    if the user has clicked in the topic list then we'll 
  1564.             //    handle the processing here
  1565.             //
  1566.             //    let the List Manager process the mouse down. this includes cell
  1567.             //    selection dragging, scrolling and double clicks by the user.
  1568.             
  1569.             //    find out where the user clicked...
  1570.             if (!this->ListHandleRef())
  1571.                 break;
  1572.             
  1573.             topic = (ABTopic *)this->TopicsRef()->GetCurrentLink();
  1574.             if (topic)
  1575.                 topicIndex = topic->Ordinal();
  1576.             else
  1577.                 topicIndex = 0;
  1578.                 
  1579.             if (::LClick(where, event->modifiers, this->ListHandleRef())) 
  1580.             {
  1581.                 //    a double click in a cell has occured.
  1582.                 //    find out in which one of the cells the user has 
  1583.                 //    double clicked in.
  1584.                 cell = ::LLastClick(this->ListHandleRef());
  1585.                 if (topicIndex && (topicIndex != (cell.v + 1)))
  1586.                     //    not the same topic...
  1587.                     ok = true;
  1588.                 else
  1589.                     ok = false;
  1590.             } else {
  1591.                 //    a normal click in the list, so find the cell
  1592.                 //    that was targeted (if any...LGetSelect _can_ return false)...
  1593.                 ::SetPt (&cell, 0, 0);
  1594.                 ok = ::LGetSelect (true, &cell, this->ListHandleRef());
  1595.                 if (ok && (topicIndex == (cell.v + 1)))
  1596.                     //    oops, the user selected the same (current) topic...
  1597.                     ok = false;
  1598.             }    //    end if block
  1599.             
  1600.             //    if we have this->TopicsRef() in this about box AND the user did indeed
  1601.             //    select a cell, jump to that topic and display
  1602.             //
  1603.             if (ok)
  1604.             {
  1605.                 ::LSetSelect (true, cell, this->ListHandleRef());
  1606.                 topic = (ABTopic *)this->TopicsRef()->GotoLink(cell.v + 1);
  1607.                 if (topic)
  1608.                     error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1609.             } else {
  1610.                 //    the user clicked in a blank area of the list, so reset the
  1611.                 //    selection to avoid having a slide showing but no topic highlighted...
  1612.                 cell.v = topicIndex - 1;
  1613.                 cell.h = 0;
  1614.                 ::LSetSelect(true, cell, this->ListHandleRef());
  1615.             } // end if (this->TopicsRef()) block
  1616.             break;
  1617.         case    kAboutBoxPreviousTopic:
  1618.         case    kAboutBoxNextTopic:
  1619.             if (itemNo == kAboutBoxPreviousTopic)
  1620.                 topic = (ABTopic *)this->TopicsRef()->PreviousLink();
  1621.             else //if (itemNo == kAboutBoxNextTopic)
  1622.                 topic = (ABTopic *)this->TopicsRef()->NextLink();
  1623.             
  1624.             if (topic)
  1625.             {
  1626.                 cell.v = cell.h = 0;
  1627.                 ok = ::LGetSelect (true, &cell, this->ListHandleRef());
  1628.                 if (ok)
  1629.                     //    deselect the current List cell
  1630.                     ::LSetSelect (false, cell, this->ListHandleRef());
  1631.                 cell.v = topic->Ordinal() - 1;
  1632.                 cell.h = 0;
  1633.                 //    select the new List cell
  1634.                 ::LSetSelect(true, cell, this->ListHandleRef());
  1635.                 ::LAutoScroll(this->ListHandleRef());
  1636.                 
  1637.                 error = topic->ResizeAndDraw(itemRect, this->GetWindow());
  1638.  
  1639.             } // end if else block
  1640.             break;
  1641.         
  1642.     }    //    end of switch block 
  1643.     
  1644.     error = this->ChangeControls();
  1645.     
  1646.     //    restore the old port
  1647.     ::SetPort (oldPort);
  1648.     
  1649.     return error;
  1650. } // end ProcessItemHit
  1651.  
  1652.  
  1653.  
  1654.  
  1655.  
  1656. /*=============================== ABox::ModalEventFilter ===============================*/
  1657. //
  1658. //    ModalEventFilter always returns a flag, "eventHandled," indicating if the dialog 
  1659. //    filter box handled the event and that the caller can now examine which item was
  1660. //    hit by the user.
  1661. //
  1662. pascal Boolean    ABox::ModalEventFilter(DialogPtr dialog, EventRecord *event, short *item)
  1663. {
  1664.     //    For alert and modal dialog boxes, the Dialog Manager provides a standard event     
  1665.     //    filter function that checks whether the user has pressed the Enter or Return key     
  1666.     //    and, if so, returns the item number of the default button. Your event filter     
  1667.     //    function should always check whether the Return key or Enter key was pressed and,     
  1668.     //    if so, return the item number of the default button in the itemHit parameter and     
  1669.     //    a function result of true. Your event filter function should also check whether     
  1670.     //    the Esc key was pressed and, if so, return the item number for the Cancel button     
  1671.     //    in the itemHit parameter and a function result of true. Your event filter function     
  1672.     //    should also respond to the Command-period key-down event as if the user had clicked     
  1673.     //    the Cancel button.    
  1674.     //        
  1675.     Boolean                eventHandled = false;
  1676.     
  1677.     char                character;
  1678.     Point                where;
  1679.     Rect                itemRect;
  1680.     short                itemType;
  1681.     Handle                listItemHandle;
  1682.  
  1683.     OSErr                error = noErr;
  1684.     
  1685.     ControlHandle        controlHandle;
  1686.     
  1687.     //    the ModalFilterProcPtr below becomes a ModalFilterUPP
  1688.     ModalFilterUPP        modalFilterUPP = NULL;
  1689.     
  1690.     ABox                *abox = NULL;
  1691.     ABTopic                *currentTopic;
  1692.     GrafPtr                oldPort;
  1693.     WindowPtr            aboxWindow;
  1694.     Boolean                aboxInBackground = false;
  1695.     Point                pseudoWhere = { 0, 0 };
  1696.     ABoxModalIndicator    modality = kABoxModal;
  1697.     long                splash;
  1698.     
  1699.     //    begin here...
  1700.     
  1701.     if (!(event && item && dialog))
  1702.         return false;
  1703.         
  1704.     abox = (ABox *)::GetWRefCon(dialog);
  1705.     if (!abox)
  1706.         return false;
  1707.  
  1708.     //    find the window
  1709.     error = abox->GetProperty (kABoxWindow, &aboxWindow, NULL);
  1710.     if (dialog != aboxWindow || (error != noErr))
  1711.         return false;
  1712.     
  1713.     //    find the splashtime...
  1714.     error = abox->GetProperty (kABoxSplashTimeSeconds, &splash, NULL);
  1715.     if (error != noErr)
  1716.         return false;
  1717.         
  1718.     error = abox->GetProperty (kABoxModalIndicator, &modality, NULL);
  1719.     if (error != noErr)
  1720.         return false;
  1721.         
  1722.     ::GetPort (&oldPort);
  1723.     ::SetPort (dialog);
  1724.     
  1725.     where = event->where;
  1726.     ::GlobalToLocal(&where);
  1727.     
  1728.     //    do the splash thing?
  1729.     if (abox->Splash(event))
  1730.     {
  1731.         //    break outta the loop
  1732.         *item = kAboutBoxOK;
  1733.         return eventHandled = true;
  1734.     } // end if block
  1735.     
  1736.     //    this step here is superfluous if we are a ModalDialog, but
  1737.     //    is required in this filter if we are a MoveableModal or
  1738.     //    ModelessDialog to avoid processing the event
  1739.     if (::IsDialogEvent (event) && (splash == kABoxNoSplash))
  1740.     {    
  1741.         ::LocalToGlobal(&pseudoWhere);
  1742.         
  1743.         ::GetDItem(dialog, kAboutBoxTopic, &itemType, &listItemHandle, &itemRect);
  1744.     
  1745.         if (::PtInRect(where, &itemRect))
  1746.             *item = kAboutBoxTopic;
  1747.     
  1748.     
  1749.         //    check out some of the mouseDown stuff...if we are modal or
  1750.         //    moveable modal and the mouseDown is NOT in our window, then
  1751.         //    we'll have to indicate this to the user. In reality, ModalDialog
  1752.         //    already does this for us, but there is no system level support
  1753.         //    for a MoveableModal dialog, so we've gotta simulate the same
  1754.         //    actions here (with the exception of allowing the menubar to happen)
  1755.         if ((event->what == mouseDown) && (modality != kABoxModal))
  1756.         {
  1757.             //    we've gotta manually track the control...
  1758.             short            controlPart;
  1759.             ControlHandle    controlHandle = NULL;
  1760.             
  1761.             eventHandled = false;
  1762.             *item = ::FindDItem (dialog, where) + 1;
  1763.             controlPart = ::FindControl (where, aboxWindow, &controlHandle);
  1764.             if (controlPart == inButton)
  1765.             {
  1766.                 controlPart = ::TrackControl (controlHandle, where, NULL);
  1767.                 if (controlPart != inButton)
  1768.                 {
  1769.                     //    forget it...void the event by setting it
  1770.                     //    to something that we'll never be concerned with
  1771.                     event->what = mouseUp;
  1772.                     *item = 0;
  1773.                 } else {
  1774.                     eventHandled = true;
  1775.                 } // end if block
  1776.             } // end if block
  1777.         } // end if block
  1778.     
  1779.         //    Key filtering schemes follow...a standard filter to
  1780.         //    recognize 'return' as OK and 'ESC' as cancel.  What this really means
  1781.         //    is that [C.K. Haun, Apple Developer Tech Support] never ever want[s] to have to
  1782.         //    use the mouse to click the cancel buttton ever again, you can just cut and
  1783.         //    paste this code from now on.
  1784.         //
  1785.         //    do standard filtering for escape and return as OK and Cancel aliases
  1786.         //    We also invert the button in the dialog, so the user get's visual feedback
  1787.         //    about the action they just took.
  1788.         //
  1789.         //    Again, if we're using the new calls, then we don't need to do this particular
  1790.         //    filtering
  1791.         
  1792.         if ((event->what == keyDown) || (event->what == autoKey))
  1793.         {
  1794.             character = event->message & charCodeMask;
  1795.             switch (character) {
  1796.  
  1797.                 case kReturnKey:
  1798.                 case kEnterKey: 
  1799.                 case kEscKey:
  1800.                     *item = kAboutBoxOK;
  1801.                     //    To give visual feedback indicating which item has been selected, you
  1802.                     //    should invert buttons that are activated by keyboard equivalents for
  1803.                     //    all alert and dialog boxes. A good rule of thumb is to invert a button
  1804.                     //    for 8 ticks, long enough to be noticeable but not so long as to be
  1805.                     //    annoying. The Control Manager performs this action whenever a user 
  1806.                     //    clicks a button, and your application should do this whenever a user
  1807.                     //    presses the keyboard equivalent of a button click.
  1808.                     //
  1809.                     controlHandle = GetControlHandle (aboxWindow, *item);
  1810.                     eventHandled = FlashControl(controlHandle);
  1811.                     break;
  1812.                     
  1813.                 case    kUpArrow:
  1814.                 case    kDownArrow:
  1815.                     *item = (character == kUpArrow) ? kAboutBoxPreviousTopic : kAboutBoxNextTopic;
  1816.                     event->where = pseudoWhere;
  1817.                     event->what = mouseDown;
  1818.                     event->message = (long)aboxWindow;
  1819.                     eventHandled = true;
  1820.                     break;
  1821.                 case    kSpace:
  1822.                 case    kLeftArrow:
  1823.                 case    kRightArrow:
  1824.                     //    the user wants to replay the slide
  1825.                     //    the user wants to see the previous slide.
  1826.                     //    the user wants to see the next slide.
  1827.                     //
  1828.                     if (character == kLeftArrow)
  1829.                     {
  1830.                         *item = kAboutBoxPrevButton;
  1831.                     } else if (character == kRightArrow) {
  1832.                         *item = kAboutBoxNextButton;
  1833.                     } else if (character == kSpace) {
  1834.                         *item = kAboutBoxPlayButton;
  1835.                     } // end if else block
  1836.                     
  1837.                     event->where = pseudoWhere;
  1838.                     event->what = mouseDown;
  1839.                     event->message = (long)aboxWindow;
  1840.                     controlHandle = GetControlHandle (aboxWindow, *item);
  1841.                     eventHandled = FlashControl(controlHandle);
  1842.                     break;
  1843.                     
  1844.                 default:
  1845.                     break;
  1846.             }    //    end switch(character) block
  1847.         } // end if block
  1848.     
  1849.     } // end if block
  1850.     
  1851.     if (event->what == updateEvt) 
  1852.     {
  1853.         //    By responding to update events for your application’s own inactive windows
  1854.         //    in this way, you allow ModalDialog to perform a minor switch when necessary
  1855.         //    so that background applications can update their windows, too.
  1856.         //
  1857.         GrafPtr                tPort;
  1858.         UpdateWindowUPP        updaterUPP = NULL;
  1859.         WindowPtr            curWindow = ::FrontWindow();
  1860.         
  1861.         ::GetPort (&tPort);
  1862.         error = abox->GetProperty (kABoxUpdater, &updaterUPP, NULL);
  1863.         
  1864.         curWindow = ::FrontWindow();
  1865.         eventHandled = false;
  1866.         while (curWindow) 
  1867.         {
  1868.             //if (abox->IsThisTheWindow(curWindow))
  1869.             if (abox->NotOurWindow(curWindow))
  1870.             {
  1871.                 ::SetPort (curWindow);
  1872.                 if (updaterUPP)
  1873.                 {
  1874.                     CallWindowUpdateProc(updaterUPP, curWindow);
  1875.                 } else {
  1876.                     //    no this->UpdaterRef(), not our update, so toss it
  1877.                     //    to the 4 winds...
  1878.                     ::BeginUpdate(curWindow);
  1879.                     ::EndUpdate(curWindow);
  1880.                 } // end if else block
  1881.                 ::SetPort (tPort);
  1882.             } else {
  1883.                 //    the event IS for us; should we bother to process it, since ModalDialog
  1884.                 //    takes care of these things for us?
  1885.                 if (modality != kABoxModal)
  1886.                 {
  1887.                     ::BeginUpdate(aboxWindow);
  1888.                     ::UpdtDialog(aboxWindow, (aboxWindow)->visRgn);
  1889.                     ::EndUpdate(aboxWindow);
  1890.                     eventHandled = true;
  1891.                 } // end if block
  1892.             } // end if else block
  1893.  
  1894.             curWindow = (WindowPtr) ((WindowPeek) curWindow)->nextWindow;
  1895.         }    //    end while block
  1896.  
  1897.     }    //    end if block 
  1898.  
  1899.     //    one final thing if we're under System 7, calling the standard filter.
  1900.     //    You MUST call the standard filter if you want any of the new dialog things to happen!
  1901.     //    The OK button border, cursor tracking, and the rest ONLY happen if you call the filter!
  1902.     //
  1903.     //    the ModalFilterProcPtr's below became ModalFilterUPP's
  1904.     error = ::GetStdFilterProc(&modalFilterUPP);
  1905.     if ((error == noErr) && modalFilterUPP)
  1906.     {
  1907.         Boolean    stdHandled = false;
  1908.         
  1909.         if (((modality == kABoxModal) && !eventHandled) || (modality != kABoxModal))
  1910.             stdHandled = CallModalFilterProc(modalFilterUPP, dialog, event, item);
  1911.     } // end if block
  1912.     
  1913.     //    save the event into the ABox object for processing later...
  1914.     error = abox->SetProperty (kABoxLastEvent, event, kABoxLastEventSize);
  1915.     
  1916.     //    Allow some of the sub-objects to process the event IF
  1917.     //    conditions are right...
  1918.     if (!abox->Splash(event))
  1919.     {
  1920.         error = abox->GetProperty (kABoxCurrentTopic, ¤tTopic, NULL);
  1921.         if (!error && currentTopic)
  1922.             (void)currentTopic->Event(event);
  1923.     } // end if block
  1924.     
  1925.     //    give some time to the threads...gotta have threads man!
  1926.     error = abox->DoThreads();
  1927.     
  1928.     //    now return to the caller...
  1929.     //
  1930.     //    from Toolbox Essentials, p. 6-136:
  1931.     //
  1932.     //    For events inside the dialog box, ModalDialog passes the event to the event 
  1933.     //    filter function pointed to in the filterProc parameter before handling the 
  1934.     //    event. When the event filter returns false, ModalDialog handles the event. If 
  1935.     //    the event filter function handles the event, the event filter function returns 
  1936.     //    true, and ModalDialog performs no more event handling.    
  1937.     //
  1938.     
  1939.     ::SetPort (oldPort);
  1940.     return (eventHandled);
  1941.  
  1942. }    //    end of function ModalEventFilter()
  1943.  
  1944.  
  1945.  
  1946.  
  1947.  
  1948. /*=============================== ABox::ChangeControls ================================*/
  1949. OSErr    ABox::ChangeControls(void)
  1950. {
  1951.     OSErr        error = noErr;
  1952.     ABTopic        *topic = NULL;
  1953.     ABSlide        *slide = NULL;
  1954.     ABIndex        slideNum = 0;
  1955.     ABListCount    slideCount = 0;
  1956.     Boolean        playableResources = false;
  1957.     
  1958.     short        itemType;
  1959.     Handle        playButtonHandle;
  1960.     Handle        nextButtonHandle;
  1961.     Handle        prevButtonHandle;
  1962.     Rect        itemRect;
  1963.     Boolean        isMovie = false;
  1964.     Boolean        hasController = false;
  1965.     Boolean        code = false;
  1966.     
  1967.     //    begin here...
  1968.     //
  1969.     this->ReportMemory();    
  1970.     
  1971.     if (this->InBackgroundFlagRef())
  1972.         return error;
  1973.         
  1974.     topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
  1975.     if (!topic)
  1976.         return paramErr;
  1977.     slide = topic->CurrentSlide();
  1978.     if (slide)
  1979.     {
  1980.         slideNum = slide->Ordinal();
  1981.         if (slide->GetResourceOfType (kABSoundResource))
  1982.             playableResources = true;
  1983.         else
  1984.             playableResources = false;
  1985.     } // end if block
  1986.  
  1987.     error = topic->GetProperty (kABTopicNumberOfSlides, &slideCount, NULL);
  1988.     error = topic->GetProperty (kABTopicIsMovie, &isMovie, NULL);
  1989.     error = topic->GetProperty (kABTopicHasMovieController, &hasController, NULL);
  1990.     if (!playableResources && isMovie && !hasController)
  1991.         playableResources = true;
  1992.         
  1993.     ::GetDItem(this->GetWindow(), kAboutBoxPrevButton, &itemType, &prevButtonHandle, &itemRect);
  1994.     ::GetDItem(this->GetWindow(), kAboutBoxNextButton, &itemType, &nextButtonHandle, &itemRect);
  1995.     ::GetDItem(this->GetWindow(), kAboutBoxPlayButton, &itemType, &playButtonHandle, &itemRect);
  1996.  
  1997.     code = (slideNum > 1) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
  1998.     error = this->CheckControl((ControlHandle)prevButtonHandle, code);
  1999.     
  2000.     code = (slideNum < slideCount) && !isMovie && (this->SplashTimeRef() == kABoxNoSplash);
  2001.     error = this->CheckControl((ControlHandle)nextButtonHandle, code);
  2002.     
  2003.     code = playableResources && (this->SplashTimeRef() == kABoxNoSplash);
  2004.     error = this->CheckControl((ControlHandle)playButtonHandle, code);
  2005.     
  2006.     return error;
  2007.     
  2008. } // end ChangeControls
  2009.  
  2010.  
  2011.  
  2012.  
  2013.  
  2014. /*=============================== ABox::ReportMemory ================================*/
  2015. void    ABox::ReportMemory(void)
  2016. {
  2017.     long        freeMemNumber;
  2018.     Str255        freeMemString;
  2019.     
  2020.     GrafPtr        oldPort;
  2021.     Rect        rect;
  2022.     
  2023.     //    begin here...
  2024.     //
  2025.     if (!this->ReportMemoryFlagRef())
  2026.         return;
  2027.         
  2028.     ::GetPort (&oldPort);
  2029.     ::SetPort (this->GetWindow());
  2030.     
  2031.     freeMemNumber = ::FreeMem();
  2032.     ::NumToString (freeMemNumber, freeMemString);
  2033.     rect.left = (this->GetWindow())->portRect.left;
  2034.     rect.bottom = (this->GetWindow())->portRect.bottom;
  2035.     rect.right = rect.left + ::StringWidth(freeMemString) * 1.20;
  2036.     rect.top = rect.bottom - kABscrollBarWidth;
  2037.     ::EraseRect (&rect);
  2038.     ::MoveTo (rect.left, rect.bottom);
  2039.     ::DrawString (freeMemString);
  2040.     ::SetPort (oldPort);
  2041.     
  2042.     return;
  2043. } // end ReportMemory
  2044.  
  2045.  
  2046.  
  2047.  
  2048.  
  2049. /*=============================== ABox::Stop ================================*/
  2050. OSErr    ABox::Stop(void)
  2051. {
  2052.     OSErr        error = noErr;
  2053.     ABTopic        *topic;
  2054.     
  2055.     //    begin here...
  2056.     //
  2057.     if (this->TopicsRef())
  2058.     {
  2059.         topic = (ABTopic *)(this->TopicsRef()->GetCurrentLink());
  2060.         if (topic)
  2061.             error = topic->Stop();
  2062.     } // end if (slides) block
  2063.     
  2064.     return error;
  2065.     
  2066. } // end Stop
  2067.  
  2068.  
  2069.  
  2070.  
  2071.  
  2072.  
  2073. // end of file